package cn.adviceclient.event;

import java.lang.reflect.Method;
import java.util.*;

public class EventBus {
    private static final EventBus INSTANCE = new EventBus();

    public static EventBus getInstance() {
        return INSTANCE;
    }

    public static class ListenerMethod {
        private final Object target;
        private final Method method;
        private final int priority;

        public ListenerMethod(Object target, Method method, int priority) {
            this.target = target;
            this.method = method;
            this.priority = priority;
        }

        public Object target() {
            return target;
        }

        public Method method() {
            return method;
        }

        public int priority() {
            return priority;
        }
    }

    private static final Map<Class<?>, List<ListenerMethod>> listeners = new HashMap<>();

    public static void register(Object listener) {
        for (Method method : listener.getClass().getDeclaredMethods()) {
            if (method.isAnnotationPresent(Listener.class) && method.getParameterCount() == 1) {
                Listener annotation = method.getAnnotation(Listener.class);
                Class<?> eventType = method.getParameterTypes()[0];
                method.setAccessible(true);
                List<ListenerMethod> methodList = listeners.computeIfAbsent(eventType, k -> new ArrayList<>());
                methodList.add(new ListenerMethod(listener, method, annotation.p()));
                // 立即排序，避免每次事件触发时都排序
                methodList.sort(Comparator.comparingInt((ListenerMethod lm) -> lm.priority()).reversed());
            }
        }
    }
    
    public static void unregister(Object listener) {
        for (List<ListenerMethod> list : listeners.values()) {
            boolean modified = list.removeIf(lm -> lm.target() == listener);
            // 如果列表发生变化，重新排序
            if (modified && !list.isEmpty()) {
                list.sort(Comparator.comparingInt((ListenerMethod lm) -> lm.priority()).reversed());
            }
        }
    }

    public static void post(Object event) {
        List<ListenerMethod> methods = listeners.get(event.getClass());
        if (methods == null) return;
        
        // 使用普通循环而不是流操作，避免额外的开销
        for (ListenerMethod lm : methods) {
            try {
                lm.method().invoke(lm.target(), event);
                if (event instanceof Event && ((Event) event).cancelled) break;
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}